import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

class ListViewDemo extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(

      appBar: AppBar(title: Text('ListViewDemo'),),

      body: SizedBox(

        width: double.infinity,

        height: double.infinity,

        child: Flex(

          direction: Axis.vertical,

          children: <Widget>[

            RaisedButton(

              child: Text('DefaultListViewDemo'),
              onPressed: () {
                Navigator.push(
                    context, MaterialPageRoute(builder: (BuildContext c) {
                  return DefaultListViewDemo();
                }));
              },
            ),


            RaisedButton(

              child: Text('ListViewBuilderDemo'),
              onPressed: () {
                Navigator.push(
                    context, MaterialPageRoute(builder: (BuildContext c) {
                  return ListViewBuilderDemo();
                }));
              },
            ),

            RaisedButton(

              child: Text('ListViewSeparated'),

              onPressed: () {
                Navigator.push(context, MaterialPageRoute(builder: (context) {
                  return ListViewSeparatedDemo();
                }));
              },

            ),


            RaisedButton(

              child: Text('无限加载列表'),

              onPressed: () {
                Navigator.push(context, MaterialPageRoute(builder: (context) {
                  return InfiniteListViewDemo();
                }));
              },

            )
          ],
        ),
      ),
    );
  }
}


///公共属性
//scrollDirection: Axis.vertical, //滚动方向
//ClampingScrollPhysics：Android下微光效果。
//BouncingScrollPhysics：iOS下弹性效果
//AlwaysScrollableScrollPhysics ：始终响应用户的滚动。
//NeverScrollableScrollPhysics ：不响应用户的滚动。
//physics: BouncingScrollPhysics(),


///ListView 各个构造函数的共同参数
//itemCount: 100,
//强制确定子组件的高度，比交给子组件自己确定高度更加有效，因为可以提前知道高度，不需要每次
//构建子组件的时候去重新计算
//itemExtent: 50,


///通过构造方法构建的ListView，适合比较少的子组件列表。
/// 这种方式会一次性把子组件全部加载出来，没有 Slicer 懒加载模型（android的复用机制）
class DefaultListViewDemo extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(

      appBar: AppBar(title: Text('使用构造方法构建ListView'),),

      body: ListView(

        children: <Widget>[

          const Text('I\'m dedicating every day to you'),
          const Text('Domestic life was never quite my style'),
          const Text('When you smile, you knock me out, I fall apart'),
          const Text('And I thought I was so smart'),
        ],
      ),
    );
  }
}


///使用builder构建。可以加载多子组件的列表，拥有 Sliver 懒加载模型
class ListViewBuilderDemo extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(

      appBar: AppBar(title: Text('ListViewBuilderDemo'),),

      body: ListView.builder(

          physics: BouncingScrollPhysics(),

          itemCount: 100,

          itemExtent: 50,

          itemBuilder: (BuildContext context, int index) {
            return ListTile(title: Text('item$index'),);
          }

      ),
    );
  }
}


///带分割线的ListView
class ListViewSeparatedDemo extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    Divider dividerBlack = Divider(color: Colors.black,);
    Divider dividerBlue = Divider(color: Colors.blue,);

    return Scaffold(

      appBar: AppBar(title: Text('分割线 ListView'),),

      body: ListView.separated(

          itemBuilder: (BuildContext context, int index) {
            return ListTile(title: Text('item $index'),);
          },

          separatorBuilder: (BuildContext context, int index) {
            return index % 2 == 0 ? dividerBlack : dividerBlue;
          },

          itemCount: 50
      ),
    );
  }
}


///无限加载列表
class InfiniteListViewDemo extends StatefulWidget {

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return InfiniteListViewDemoState();
  }
}

class InfiniteListViewDemoState extends State<InfiniteListViewDemo> {

  static const String loadingTag = 'loadingTag';
  List<String> _words = [loadingTag];

  @override
  void initState() {
    super.initState();

    _retrieveData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(

      appBar: AppBar(title: Text('无限加载列表'),),

      body: ListView.separated(

          physics: BouncingScrollPhysics(),

          itemBuilder: (BuildContext context, int index) {

            //添加数据的时候减少一位把loadingTag一直放在最后
            if(_words[index] == loadingTag){

              if(_words.length - 1 < 60){

                //异步获取数据
                _retrieveData();

                //显示加载loading
                return Container(

                  padding: const EdgeInsets.all(16.0),
                  alignment: Alignment.center,
                  child: SizedBox(

                    width: 24.0,
                    height: 24.0,
                    child: CircularProgressIndicator(strokeWidth: 2.0,),
                  ),
                );

              }else{

                //已经加载100，没有数据了
                return Container(

                  alignment: Alignment.center,
                  padding: EdgeInsets.all(16.0),
                  child: Text('没有更多了',style: TextStyle(color: Colors.grey),),
                );

              }

            }else{

              if(index == 0){

                return Container(

                  child: Icon(Icons.title),
                );
              }else{

                return ListTile(title: Text(_words[index]+'$index'),);
              }

            }


          },

          separatorBuilder: (BuildContext context, int index) {
            return Divider(color: Colors.grey,);
          },
          itemCount: _words.length),

    );
  }

  _retrieveData() {
    Future.delayed(Duration(seconds: 2)).then((e) {
      _words.insertAll(_words.length - 1,
//           generateWordPairs().take(20).map((e) => e.asPascalCase).toList()
          generateWordPairs().take(20).map((e) => e.asPascalCase).toList()
      );

      setState(() {});
    });
  }
}